package com.bdi.mqtt_broker.handler.ssl;

import com.bdi.mqtt_broker.config.BrokerConfig;
import com.bdi.mqtt_broker.main.BrokerMain;
import io.netty.handler.ssl.ClientAuth;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslContextBuilder;
import io.netty.handler.ssl.SslProvider;
import lombok.extern.slf4j.Slf4j;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.security.GeneralSecurityException;
import java.util.Arrays;
import java.util.List;

/**
 * @author WangNing
 * @version 1.0
 * @date 2020/12/10 21:57
 */
@Slf4j
public class SslContextFactory {


    static {
        // 解决algid parse error, not a sequence
        // https://blog.csdn.net/ls0111/article/details/77533768
        java.security.Security.addProvider(
                new org.bouncycastle.jce.provider.BouncyCastleProvider()
        );
    }

    public static SslContext getSSLContext(String fullchainFile, String privkeyFile, String sslProvider) throws IOException, GeneralSecurityException {
        try {
            boolean useOpenSSl = false;


            if("openssl".equalsIgnoreCase(sslProvider)){
                log.info("Ssl Factory Use Openssl");
                useOpenSSl = true;
            }


            //jdk8删除gcm加密
            List<String> ciphers = Arrays.asList("TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA","TLS_RSA_WITH_AES_128_CBC_SHA", "TLS_RSA_WITH_AES_256_CBC_SHA");

            return SslContextBuilder.forServer(new File(fullchainFile),new File(privkeyFile))
                    .protocols("TLSv1.1", "TLSv1.2")
                    .sslProvider(useOpenSSl?SslProvider.OPENSSL:SslProvider.JDK)
                    .clientAuth(ClientAuth.NONE)
                    .trustManager(new File(fullchainFile))
//                    .ciphers(ciphers)
                    .build();

        } catch (IOException e) {
            log.warn("Failed to establish SSL Context");
            log.debug("Failed to establish SSL Context", e);
            throw e;
        }
    }



    private static void closeSilent(final InputStream is) {
        if (is == null)
            return;
        try {
            is.close();
        } catch (Exception ignored) {
        }
    }
}
